/*
 * RefBoxClient.cpp
 *
 *  Created on: 2010-10-02
 *      Author: kamil
 */

#include "mgr/refboxclient/RefBoxClient.h"

#include <boost/bind.hpp>

using boost::asio::ip::udp;
using namespace std;

RefBoxClient::RefBoxClient(boost::asio::io_service & io_service)
	:io_service(io_service), socket(io_service), lastCmd(CMD_UNDEFINED), lastCmdNr(-1)
{
	boost::asio::ip::address listenAddress(boost::asio::ip::address::from_string("0.0.0.0"));
	boost::asio::ip::address_v4 refBoxAddress(boost::asio::ip::address_v4::from_string("224.5.23.1"));
	udp::endpoint refBoxEnpoint(listenAddress, 10001);
	socket.open(udp::v4());
	socket.set_option(udp::socket::reuse_address(true));
	socket.bind(refBoxEnpoint);
	socket.set_option(boost::asio::ip::multicast::join_group(refBoxAddress));

	prepareRead();
}

RefBoxClient::~RefBoxClient() {
	socket.close();
}

void RefBoxClient::prepareRead()
{
	socket.async_receive(	boost::asio::buffer(&data, sizeof(data)),
							boost::bind(&RefBoxClient::handleRead, this,
							boost::asio::placeholders::error,
							boost::asio::placeholders::bytes_transferred)
						);
}

void RefBoxClient::handleRead(const boost::system::error_code & error, std::size_t)
{
	// TODO: read for time remaining is probably broken
	packet.cmd 				= data[0];
	packet.cmd_counter 		= static_cast<unsigned char>(data[1]);
	packet.goals_blue 		= static_cast<unsigned char>(data[2]);
	packet.goals_yellow 	= static_cast<unsigned char>(data[3]);
	packet.time_remaining 	= static_cast<unsigned short>(data[4]);

//	LOG4CXX_DEBUG(logger, "Read packet: "
//			<<packet.cmd<<" | "
//			<<(int)packet.cmd_counter<<" | "
//			<<(int)packet.goals_blue<<" | "
//			<<(int)packet.goals_yellow<<" | "
//			<<(int)packet.time_remaining);

	if (packet.cmd_counter > lastCmdNr){
		lastCmdNr = packet.cmd_counter;
		lastCmd = parseCommand(packet.cmd);
//		LOG4CXX_INFO(logger, "Referee command received, code ["<<packet.cmd<<"] mapped to ["<<lastCmd<<"] cmdNr: ["<<lastCmdNr<<"]");
	}

	prepareRead();
}

RefereeCmd RefBoxClient::parseCommand(char command){
	switch (command){
	case 'H': return CMD_HALT;
	case 'S': return CMD_STOP;
	case ' ': return CMD_READY;
	case 's': return CMD_START;
	case '1': return CMD_BEGIN_FIRST_HALF;
	case 'h': return CMD_BEGIN_HALF_TIME;
	case '2': return CMD_BEGIN_SECOND_HALF;
	case 'o': return CMD_BEGIN_OVERTIME_HALF_1;
	case 'O': return CMD_BEGIN_OVERTIME_HALF_2;
	case 'a': return CMD_BEGIN_PENALTY_SHOOTOUT;

	case 'k': return CMD_KICKOFF_YELLOW;
	case 'K': return CMD_KICKOFF_BLUE;
	case 'p': return CMD_PENALTY_YELLOW;
	case 'P': return CMD_PENALTY_BLUE;
	case 'f': return CMD_DIRECT_FREE_KICK_YELLOW;
	case 'F': return CMD_DIRECT_FREE_KICK_BLUE;
	case 'i': return CMD_INDIRECT_FREE_KICK_YELLOW;
	case 'I': return CMD_INDIRECT_FREE_KICK_BLUE;

	case 't': return CMD_TIMEOUT_YELLOW;
	case 'T': return CMD_TIMEOUT_BLUE;
	case 'z': return CMD_TIMEOUT_END_YELLOW;
	case 'Z': return CMD_TIMEOUT_END_BLUE;
	case 'g': return CMD_GOAL_SCORED_YELLOW;
	case 'G': return CMD_GOAL_SCORED_BLUE;
	case 'd': return CMD_DECREASE_GOAL_SCORE_YELLOW;
	case 'D': return CMD_DECREASE_GOAL_SCORE_BLUE;
	case 'y': return CMD_YELLOW_CARD_YELLOW;
	case 'Y': return CMD_YELLOW_CARD_BLUE;
	case 'r': return CMD_RED_CARD_YELLOW;
	case 'R': return CMD_RED_CARD_BLUE;
	case 'c': return CMD_CANCEL;

	default:  return CMD_UNDEFINED;
	}
}
